package com.demo2do.mobile.web.interceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.WebUtils;

import com.demo2do.mobile.Constant;

/**
 * 
 * @author mohanlan
 *
 */
public class MobileDetectInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(MobileDetectInterceptor.class);

    private static final String SAVED_REQUEST = "MOBILE_SNIFFER_REQUEST";

    /**
     * User mobile key stored in the cookie
     */
    private String mobileKey = Constant.MOBILE_KEY;

    /**
     * URL where once no mobile found in the cookie, the browser should redirect to
     */
    private String loginUrl;

    /**
     * mobileKey The mobileKey to set
     * @param mobileKey
     */
    public void setMobileKey(String mobileKey) {
        this.mobileKey = mobileKey;
    }

    /**
     * loginUrl The loginUrl to set
     * @param loginUrl
     */
    public void setLoginUrl(String loginUrl) {
        this.loginUrl = loginUrl;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        
        if(handler instanceof HandlerMethod) {
            
            if(logger.isDebugEnabled()) {
                logger.debug("MobileDetectInterceptor#preHandle() - To determine this request can be visited without mobile or not.");
            }
            
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            MobileDetect mobileDetect = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), MobileDetect.class);
            
            // Return super preHandler
            if(mobileDetect == null ) {
                logger.info("MobileDetectInterceptor#preHandle() - no mobile detect interceptor, return super prehandle");
                return super.preHandle(request, response, handler); 
            }
            
            // Start MobileDetectInterceptor
            logger.info("MobileDetectInterceptor#preHandle() - start check mobile detect interceptor");
            
            // 1. Get mobile cookie
            logger.info("MobileDetectInterceptor#preHandle() - Get mobile cookie with mobile cookie key [{}].", mobileKey);
            Cookie mobileCookie = WebUtils.getCookie(request, mobileKey);
            
            // 2. mobileDetect do not need login
            if(!mobileDetect.autoLogin() ){
                logger.trace("MobileDetectInterceptor#preHandle() - This controller does not need to login, just return to super prehandler");
                return super.preHandle(request, response, handler);
            }
            
            // 3. need login and mobile cookie is empty
            if(mobileDetect.autoLogin() && mobileCookie == null) {
                
                saveOriginalRequest(request);  // Save original request URL
                
                String resolvedLoginUrl = loginUrl.startsWith("http") ?
                        loginUrl : (com.demo2do.core.web.utils.WebUtils.getRealServerPath(request) + loginUrl);
                logger.trace("MobileDetectInterceptor#preHandle() - The resolved login URL is [{}].", resolvedLoginUrl);
                
                response.sendRedirect(resolvedLoginUrl);
                return false;
            }
        }
        
        return super.preHandle(request, response, handler);
    }

    /**
     * Save original request in HTTP session for further reference
     * 
     * @param request
     */
    private void saveOriginalRequest(HttpServletRequest request) {
        
        // Construct original URL from request URI and query string
        String originalUri = com.demo2do.core.web.utils.WebUtils.getRealRequestURI(request);
        String queryString = request.getQueryString();
        
        String originalUrl = StringUtils.isBlank(queryString) ? originalUri : (originalUri + "?" + queryString);
        
        // Save the original URL in the session currently
        HttpSession httpSession = request.getSession();
        httpSession.setAttribute(SAVED_REQUEST, originalUrl);
    }
}
